﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Diagnostics;
using System.IO;

namespace crmbl.Azure.Globals
{
    public enum EventLevel
    {
        Critical,
        Error,
        Warning,
        Information,
        Verbose,
        Unknown
    }

    public static class Logger
    {
        public static void WriteMessage(String message)
        {
            WriteEventLogMessage(message, EventLevel.Information, 0, null, null, null);
        }

        public static void WriteMessage(String message, EventLevel level, int id)
        {
            WriteEventLogMessage(message, level, id, null, null, null);
        }

        private static String GetConfigurationValueIfExists(String configurationValueName, String nullValue)
        {
            return (ConfigurationManager.AppSettings[configurationValueName].ToString() != String.Empty) ? ConfigurationManager.AppSettings[configurationValueName] : nullValue;
        }

        private static void WriteEventLogMessage(String message, EventLevel level = EventLevel.Information, int id = 0, String source = null, String logName = null, Byte[] data = null)
        {
            try
            {
                if (logName == null)
                {
                    // The log name was not specified, look in the configuration
                    logName = GetConfigurationValueIfExists("Logger-EventLog-LogName", "Application");
                    source = GetConfigurationValueIfExists("Logger-EventLog-Source", "");
                }

                try
                {
                    // Create the Event Source if it does not exist
                    if (!EventLog.SourceExists(source))
                        EventLog.CreateEventSource(source, logName);
                }
                catch (Exception ex)
                {
                    // Failed to create the event source
                    // This is a common failure, find more information
                    throw ex;
                }

                (new EventLog(logName, ".", source)).WriteEntry(message, ConvertEventLevelToWindowsEventLogEntryType(level), id, short.MinValue, data);
            }
            catch (Exception ex)
            {
                LogInternalFailure(ex);
            }
        }

        private static EventLogEntryType ConvertEventLevelToWindowsEventLogEntryType(EventLevel level)
        {
            switch (level)
            {
                case EventLevel.Critical:
                    return EventLogEntryType.Error;
                case EventLevel.Error:
                    return EventLogEntryType.Error;
                case EventLevel.Information:
                    return EventLogEntryType.Information;
                case EventLevel.Unknown:
                    return EventLogEntryType.Information;
                case EventLevel.Verbose:
                    return EventLogEntryType.Information;
                case EventLevel.Warning:
                    return EventLogEntryType.Warning;
                default:
                    return EventLogEntryType.Information;
            }
        }

        private static void LogInternalFailure(Exception ex)
        {
            try
            {
                //TODO: Find fatal
            }
            catch (Exception) { } // Digest
        }


        public static String FormatParametersToString(String paramName1, object paramValue1, String paramName2 = null, object paramValue2 = null, String paramName3 = null, object paramValue3 = null, String paramName4 = null, object paramValue4 = null, String paramName5 = null, object paramValue5 = null, String paramName6 = null, object paramValue6 = null)
        {
            return FormatParametersToString(SqlHelper.GenerateParameterDictionary(paramName1, paramValue1, paramName2, paramValue2, paramName3, paramValue3, paramName4, paramValue4, paramName5, paramValue5, paramName6, paramValue6));
        }

        public static String FormatParametersToString(Dictionary<String,Object> d)
        {
            StringBuilder s = new StringBuilder();

            s.Append("{");

            int i = 0;
            foreach (KeyValuePair<String, Object> kvp in d)
            {
                s.Append("\""+kvp.Key+"\": \""+kvp.Value+"\"");

                if (i != d.Count - 1)
                {
                    s.Append(",");
                }
            }

            s.Append("}");

            return s.ToString();
        }

    }
}
